package cn.tedu.charging.device.service.impl;

import cn.tedu.charging.common.pojo.constant.DeviceCacheKey;
import cn.tedu.charging.common.pojo.utils.JsonUtils;
import cn.tedu.charging.common.pojo.vo.StationInfoVO;
import cn.tedu.charging.device.dao.mapper.DeviceMapper;
import cn.tedu.charging.device.pojo.po.GunStatusUpdatePO;
import cn.tedu.charging.device.pojo.po.StationPO;
import cn.tedu.charging.device.service.DeviceService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void DeviceUpdateGunId2Order(Integer gunId, Integer gunStatus) {
        UpdateWrapper<GunStatusUpdatePO> updateWrapper = new UpdateWrapper<GunStatusUpdatePO>();
        updateWrapper.eq("id", gunId);
        GunStatusUpdatePO gunStatusUpdatePO = new GunStatusUpdatePO();
        gunStatusUpdatePO.setGunStatus(gunStatus);
        deviceMapper.update(gunStatusUpdatePO, updateWrapper);
    }

    @Autowired
    private RedisTemplate<String, Serializable> redisTemplate;

    @Override
    public List<StationInfoVO> getNearStations(Double longitude, Double latitude, Double radius) {
        BoundGeoOperations<String, Serializable> stations = redisTemplate.boundGeoOps(DeviceCacheKey.STATION_LOCATION_KEY);
        ValueOperations<String, Serializable> valueOperations = redisTemplate.opsForValue();
        HashOperations<String, Object, Object> hashOperations = redisTemplate.opsForHash();

        Point point = new Point(longitude, latitude);
        Distance distance = new Distance(radius, Metrics.KILOMETERS);
        Circle circle = new Circle(point, distance);
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs();
        args.includeDistance();
        args.includeCoordinates();
        GeoResults<RedisGeoCommands.GeoLocation<Serializable>> geoResults = stations.radius(circle, args);
        List<StationInfoVO> stationInfoVOS = new ArrayList<>();
        for (GeoResult<RedisGeoCommands.GeoLocation<Serializable>> geoResult : geoResults) {

            Serializable name = geoResult.getContent().getName();
            String stationInfoKey = DeviceCacheKey.STATION_DETAIL_STRING_KEY + name;
            Serializable serializable = valueOperations.get(stationInfoKey);
            double stationDistance = geoResult.getDistance().getValue();
            Point stationPoint = geoResult.getContent().getPoint();

            String stationInfoHashBigKey = DeviceCacheKey.STATION_DETAIL_HASH_KEY + name;
            String stationInfoHashSmallKey = "name";
            Object object = hashOperations.get(stationInfoHashBigKey, stationInfoHashSmallKey);
            Map<Object, Object> entries = hashOperations.entries(stationInfoHashBigKey);
            Object smallMamKeyName = entries.get("name");
            Object deviceNumber = entries.get("deviceNumber");
            Object operatorId = entries.get("operatorId");
            if (serializable != null) {
                StationPO stationPO = JsonUtils.fromJson(String.valueOf(serializable), StationPO.class);
                if (stationPO != null) {
                    StationInfoVO stationInfoVO = new StationInfoVO();
                    stationInfoVO.setStationId(Integer.valueOf(String.valueOf(name)));
                    stationInfoVO.setStationName(stationPO.getStationName());
                    stationInfoVO.setLongitude(stationPoint.getX());
                    stationInfoVO.setLatitude(stationPoint.getY());
                    stationInfoVO.setOperatorId(stationPO.getOperatorId());
                    stationInfoVO.setDistance(stationDistance);
                    stationInfoVO.setDeviceNumber(stationPO.getDeviceNumber());
                    stationInfoVOS.add(stationInfoVO);
                }
            }
        }

        return stationInfoVOS;
    }

    @Override
    public StationInfoVO geStationDetail(Integer id) {
        ValueOperations<String, Serializable> valueOperations = redisTemplate.opsForValue();
        String stationInfoKey = DeviceCacheKey.STATION_DETAIL_STRING_KEY + id;
        Serializable serializable = valueOperations.get(stationInfoKey);
        if (serializable != null) {
            StationPO stationPO = JsonUtils.fromJson(String.valueOf(serializable), StationPO.class);
            if (stationPO != null) {
                StationInfoVO stationInfoVO = new StationInfoVO();
                stationInfoVO.setStationId(Integer.valueOf(String.valueOf(stationPO.getId())));
                stationInfoVO.setStationName(stationPO.getStationName());
                stationInfoVO.setOperatorId(stationPO.getOperatorId());

                stationInfoVO.setDeviceNumber(stationPO.getDeviceNumber());
                return stationInfoVO;
            }
        }
        return new StationInfoVO();
    }

}
